{
  aiohttp,
  alive-progress,
  build,
  clang-tools,
  click,
  colorama,
  coloredlogs,
  cryptography,
  debugpy,
  diskcache,
  fetchFromGitHub,
  fetchpatch,
  glib,
  gn,
  googleapis-common-protos,
  ipython,
  jinja2,
  json5,
  jsonschema,
  lark,
  lib,
  libnl,
  mobly,
  mypy,
  mypy-protobuf,
  ninja,
  openssl,
  packaging,
  parameterized,
  pip-tools,
  pkg-config,
  pkgconfig,
  prompt-toolkit,
  protobuf,
  psutil,
  ptpython,
  pyelftools,
  pyfakefs,
  pygments,
  pykwalify,
  pyperclip,
  pyserial,
  python,
  python-daemon,
  python-path,
  pythonOlder,
  pyyaml,
  requests,
  setuptools,
  six,
  sphinx,
  sphinx-argparse,
  sphinx-design,
  stdenv,
  tabulate,
  tornado,
  types-pyyaml,
  types-requests,
  watchdog,
  websockets,
  zap-chip,
}:

stdenv.mkDerivation rec {
  pname = "home-assistant-chip-wheels";
  version = "2025.7.0";
  src = fetchFromGitHub {
    owner = "home-assistant-libs";
    repo = "chip-wheels";
    tag = version;
    fetchSubmodules = false;
    leaveDotGit = true;
    hash = "sha256-SfhsM2RPghFPx0qtoHsXVymwmOWFiEGAyLx6FeB++dg=";
    postFetch = ''
      cd $out
      # Download connectedhomeip.
      git fetch
      git reset --hard HEAD
      git submodule update --init --depth 1 connectedhomeip

      # Initialize only necessary submodules.
      cd connectedhomeip
      ${python.interpreter} scripts/checkout_submodules.py --platform linux --shallow

      # Keep the output deterministic.
      cd $out
      # in case python decided to leave a .pyc file, for example
      git clean -fxd
      rm -rf .git/
    '';
  };

  strictDeps = true;

  nativeBuildInputs = [
    gn
    pkg-config
    ninja
    clang-tools
    zap-chip
    # gdbus-codegen
    glib
    pkgconfig
    python
    # dependencies of build scripts
    click
    jinja2
    lark
    python-path
    setuptools
    build
    pip-tools
  ];

  propagatedBuildInputs = [
    openssl
    glib
    libnl
  ];

  patches = [
    (fetchpatch {
      # Fix building with newer gn version
      name = "pw_protobuf_compiler-Create-a-new-includes.txt-for-each-toolchain.patch";
      # https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/300272
      url = "https://pigweed.googlesource.com/pigweed/pigweed/+/b66729b90fcb9df2ee4818f6d4fff59385cdbc80^!?format=TEXT";
      decode = "base64 -d";
      stripLen = 1;
      extraPrefix = "connectedhomeip/third_party/pigweed/repo/";
      hash = "sha256-6ss3j8j69w7EMio9mFP/EL2oPqQ2sLh67eWsJjHdDa8=";
    })
    # fix `ModuleNotFoundError: No module named 'matter'`
    # https://github.com/project-chip/connectedhomeip/pull/39826
    (fetchpatch {
      url = "https://github.com/project-chip/connectedhomeip/commit/78c6a7e15658f66658eb9f780e1a0c0c176a67d7.patch";
      stripLen = 1;
      extraPrefix = "connectedhomeip/";
      hash = "sha256-s5t9DvmZVpnVelrN9+Ekn0OJl/VouXUGKCgu/PTLHBI=";
    })
  ];

  postPatch = ''
    cd connectedhomeip
    export HOME=$(mktemp -d)

    patchShebangs --build scripts

    for patch in ../*.patch; do
      patch -p1 < $patch
    done

    # ecdsa is insecure and only used in tests
    patch -p1 < ${./dont-import-ecdsa.patch}

    # unpin dependencies
    # there are many files to modify, in different formats
    sed -i 's/==.*$//' third_party/pigweed/repo/pw_env_setup/py/pw_env_setup/virtualenv_setup/python_base_requirements.txt
    sed -i 's/==[^;]*//' scripts/setup/constraints.txt scripts/tests/requirements.txt
    sed -i 's/\(^ \+[a-zA-Z0-9-]*\)[=~><]=[^;]*/\1/' third_party/pigweed/repo/pw_protobuf_compiler/py/setup.cfg third_party/pigweed/repo/pw_protobuf/py/setup.cfg third_party/pigweed/repo/pw_protobuf_compiler/py/setup.cfg
    # remove a few dependencies not packaged in nixpkgs and which are apparently
    # not needed to build the python bindings of chip
    sed -i -e '/sphinxcontrib-mermaid/d' -e '/types-six/d' -e '/types-pygment/d' -e '/types-pyserial/d' third_party/pigweed/repo/*/py/setup.cfg

    # obtained by running a build in nix-shell with internet access
    cp ${./pigweed_environment.gni} build_overrides/pigweed_environment.gni

    # some code is generated by a templating tool (zap-cli)
    scripts/codepregen.py ./zzz_pregenerated/

    # `pip._internal.exceptions.InstallationError: ''${PW_PROJECT_ROOT}/scripts/py_matter_idl is not a valid editable requirement`
    substituteInPlace scripts/tests/requirements.txt \
      --replace-fail '-e ''${PW_PROJECT_ROOT}/scripts/py_matter_idl' "" \
      --replace-fail '-e ''${PW_PROJECT_ROOT}/scripts/py_matter_yamltests' ""
  '';

  # the python parts of the build system work as follows
  # gn calls pigweed to read a dozen different files to generate
  # a file looking like requirements.txt. It then calls pip
  # to install this computed list of dependencies into a virtualenv.
  # Of course, pip fails in the sandbox, because it cannot download
  # the python packages.
  # The documented way of doing offline builds is to create a folder
  # with wheel files for all dependencies and point pip to it
  # via its configuration file or environment variables.
  # https://pigweed.dev/python_build.html#installing-offline
  # The wheel of a python package foo is available as foo.dist.
  # So that would be easy, but we also need wheels for transitive dependencies.
  # the function saturateDependencies below computes this transitive closure.
  #
  # yes this list of dependencies contains both build tools and proper dependencies.
  env.PIP_NO_INDEX = "1";
  env.PIP_FIND_LINKS =
    let
      dependencies = [
        aiohttp
        alive-progress
        colorama
        coloredlogs
        click
        cryptography
        debugpy
        diskcache
        googleapis-common-protos
        ipython
        jinja2
        json5
        jsonschema
        lark
        mobly
        mypy
        mypy-protobuf
        packaging
        parameterized
        pkgconfig
        prompt-toolkit
        protobuf
        psutil
        ptpython
        pyfakefs
        pyelftools
        pygments
        pykwalify
        pyperclip
        pyserial
        python-daemon
        python-path
        pyyaml
        requests
        six
        sphinx
        sphinx-argparse
        sphinx-design
        tabulate
        tornado
        types-pyyaml
        types-requests
        watchdog
        websockets
      ];
      filterNull = list: lib.filter (dep: dep != null) list;
      toItem = dep: {
        inherit dep;
        key = dep.name;
      };
      saturatedDependencies = lib.genericClosure {
        startSet = map toItem (filterNull dependencies);
        operator = item: map toItem (filterNull ((item.dep).propagatedBuildInputs or [ ]));
      };
      saturatedDependencyList = lib.filter (dep: dep ? dist && dep != null) (
        map (item: item.dep) saturatedDependencies
      );
    in
    lib.concatMapStringsSep " " (dep: "file://${dep.dist}") saturatedDependencyList;

  gnFlags = [
    ''chip_project_config_include_dirs=["//.."]''
    ''chip_crypto="openssl"''
    ''enable_rtti=true''
    ''chip_config_memory_debug_checks=false''
    ''chip_config_memory_debug_dmalloc=false''
    ''chip_mdns="minimal"''
    ''chip_minmdns_default_policy="libnl"''
    ''chip_python_version="${lib.versions.majorMinor python.version}"''
    ''chip_python_platform_tag="any"''
    ''chip_python_package_prefix="home-assistant-chip"''
    ''custom_toolchain="custom"''
    ''target_cc="${stdenv.cc.targetPrefix}cc"''
    ''target_cxx="${stdenv.cc.targetPrefix}c++"''
    ''target_ar="${stdenv.cc.targetPrefix}ar"''
  ];

  preBuild = ''
    export NIX_CFLAGS_COMPILE="$($PKG_CONFIG --cflags glib-2.0) -O2 -Wno-error"
    export NIX_CFLAGS_LINK="$($PKG_CONFIG --libs gio-2.0) $($PKG_CONFIG --libs gobject-2.0) $($PKG_CONFIG --libs glib-2.0)"
  '';

  ninjaFlags = [ "chip-repl" ];

  installPhase = ''
    runHook preInstall

    cp -r controller/python $out

    runHook postInstall
  '';

  meta = {
    description = "Python wheels for APIs and tools related to CHIP";
    homepage = "https://github.com/home-assistant-libs/chip-wheels";
    changelog = "https://github.com/home-assistant-libs/chip-wheels/releases/tag/${src.tag}";
    license = lib.licenses.asl20;
    teams = [ lib.teams.home-assistant ];
  };

}
